package locusts.client;

import java.awt.BorderLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.net.InetSocketAddress;
import javax.swing.JFrame;
import locusts.common.GameConfig;
import locusts.common.Player;
import locusts.common.WorldModel;
import org.apache.mina.common.ConnectFuture;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.transport.socket.nio.SocketConnector;
import org.apache.mina.transport.socket.nio.SocketConnectorConfig;

/**
 * 
 * @author Hamish Morgan
 */
public class Client {

    private static final int DEFAULT_SERVER_PORT = 9123;
    private static final String DEFAULT_SERVER_HOST = "localhost";
    private static final String DEFAULT_PLAYER_NAME = "Unnamed Player";
    //
    private final Player player;
    private RenderPanel rendererPanel;
    ClientHandler clientHandler;

    public Client() {
        this(DEFAULT_SERVER_HOST, DEFAULT_SERVER_PORT,
                DEFAULT_PLAYER_NAME);
    }

    public Client(String host, int port, String name) {
        player = new Player(name);
        rendererPanel = new RenderPanel(new RenderConfig());
        JFrame window = new GameWindow();
        window.getContentPane().add(rendererPanel, BorderLayout.CENTER);

        rendererPanel.addMouseMotionListener(new MouseInput());
        window.setVisible(true);
        clientHandler = new ClientHandler(new InetSocketAddress(host,
                port));
    }

    private class MouseInput extends MouseMotionAdapter {

        @Override
        public void mouseMoved(MouseEvent e) {
            super.mouseMoved(e);
            player.setLocation(e.getX(), e.getY());
            clientHandler.write(player);
        }
    }

    class ClientHandler extends IoHandlerAdapter {

        private final InetSocketAddress address;
        private IoSession session;

        public ClientHandler(InetSocketAddress address) {
            session = null;
            this.address = address;
            connect();
        }

        public void write(Object message) {
            if (session == null)
                return;
            session.write(message);
        }

        private void connect() {
            SocketConnector connector = new SocketConnector();
            SocketConnectorConfig cfg = new SocketConnectorConfig();
            cfg.getFilterChain().addLast("codec", new ProtocolCodecFilter(
                    new ObjectSerializationCodecFactory()));
            ConnectFuture cf = connector.connect(address, this, cfg);
        }

        @Override
        public void sessionOpened(IoSession s) throws Exception {
            session = s;
        }

        @Override
        public void exceptionCaught(IoSession session, Throwable cause)
                throws Exception {
            cause.printStackTrace();
            session.close();
        }

        @Override
        public void messageReceived(IoSession session, Object message)
                throws Exception {
            if (message.getClass().equals(WorldModel.class)) {
                rendererPanel.setWorld((WorldModel) message);
                rendererPanel.repaint();
            } else if (message.getClass().equals(GameConfig.class)) {
                rendererPanel.setGameConfig((GameConfig) message);
                rendererPanel.repaint();
            }
        }
    }

    public static class GameWindow extends JFrame {

        public GameWindow() {
            setSize(400, 500);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setTitle("MouseTag!!!!!!");
        }
    }
}
